package com.rabbit.handler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.*;

/**
 * <h1>线程池封装</h1>
 *
 * @author zjw
 * @date 2022/1/14 9:25
 */
@Slf4j
public class MyExecutorService extends ThreadPoolExecutor {

    /**
     * 执行时间
     */
    private final ConcurrentHashMap<String, Date> startTimes;

    /**
     * 线程池名称
     */
    private final String poolName;

    public MyExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
                             RejectedExecutionHandler rejectedHandler, String poolName) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                ThreadFactoryBuilder.create().setNamePrefix(String.format("%s-线程", poolName)).build(), rejectedHandler);
        this.poolName = poolName;
        this.startTimes = new ConcurrentHashMap<>();
    }

    /**
     * 统计线程池情况
     */
    @Override
    public void shutdown() {
        log.info("{}-线程池shutdown时. 正在执行任务数: {}, 队列中剩余任务数: {}", this.poolName, this.getActiveCount(), this.getQueue().size());
        super.shutdown();
    }


    /**
     * 记录任务开始时间
     */
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        startTimes.put(String.valueOf(r.hashCode()), DateUtil.date());
    }

    @Override
    public void execute(Runnable command) {
        super.execute(command);
    }

    @Override
    protected void afterExecute(Runnable command, Throwable t) {
        Date startDate = startTimes.remove(String.valueOf(command.hashCode()));
        long diff = DateUtil.date().getTime() - startDate.getTime();
        log.info("{}-任务执行成功，耗时: {} ms, 线程池初始线程数: {}, 核心线程数: {}, 正在执行的任务数量: {}, 队列里缓存的任务数量: {},线程池是否关闭: {} ",
                this.poolName, diff, this.getPoolSize(), this.getCorePoolSize(), this.getActiveCount(), this.getQueue().size(), this.isShutdown());
        super.afterExecute(command, t);
    }

}
